package middleware.p2p;

import java.io.StringWriter;
import java.util.LinkedList;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlTransient;
import javax.xml.bind.annotation.XmlType;

import middleware.p2p.log.XmlSerializable;
/**
 *	Classe contenente i dati di un Workflow.
 *	I workflow non sono altro che un insieme di Task identificati da un ID.
 *	@see	TaskDescriptor	
 */
@XmlRootElement(name="workflow")
@XmlType(propOrder={"tasks"})
public class Workflow implements XmlSerializable {
    /**
	 * 	Campo necessario alla serializzazione
	 */
	private static final long serialVersionUID = -4214048129557435195L;
	/**
     * 	Lista interna dei TaskDescriptor che compongono il Workflow
     */
	@XmlElementRef
    private LinkedList<TaskDescriptor> tasks;
    /**
     * 	Identificativo del Workflow
     */
    @XmlAttribute(name="id")
    private int ID;
    /**
     * 	Costruttore di default della classe.
     * 	Il costruttore inizializza la lista interna e imposta l'ID a -1.
     */
    public Workflow(){
        tasks = new LinkedList<TaskDescriptor>();
        this.ID=-1;
    }
    /**
     * 	Metodo per ottenere un array contenente tutti i TaskDescriptor che compongono il WorkFlow.
     * 	@return	L'insieme dei TaskDescriptor
     */
    @XmlTransient
    public TaskDescriptor[] getTasks() {
        return tasks.toArray(new TaskDescriptor[tasks.size()]);
    }
    /**
     * 	Metodo per aggiungere un array di TaskDescriptor al Workflow
     * 	@param	tasks	Array di TaskDescriptor da aggiungere al Workflow.
     */
    public void setTasks(TaskDescriptor[] tasks) {
        this.tasks.clear();
        for(TaskDescriptor td : tasks){
            this.tasks.add(td);
        }
    }
    /**
     * 	Metodo per ottenere l'identificativo del Workflow
     * 	@return L'identificativo del Workflow
     */
    @XmlTransient
    public int getID() {
        return ID;
    }
    /**
     * 	Metodo per impostare l'identificativo del Workflow
     * 	@param 	ID	L'identificativo da impostare.
     */
    public void setID(int ID) {
        this.ID = ID;
    }
    /**
     * 	Metodo per ottenere il TaskDescriptor associato ad un indice.
     * 	@param 	index	Indice del TaskDescriptor da recuperare.
     * 	@return	Il TaskDescriptor desiderato.
     */
    //@XmlTransient
    public TaskDescriptor getTask(int index){
        return this.tasks.get(index);
    }
    /**
     * Metodo per aggiungere un taskdescriptor al workflow
     * @param Il TaskDescriptor da aggiungere al workflow
     * @return esito dell'operazione: "1" add eseguito correttamente, "0" errore
     */
    public int addTask(TaskDescriptor ts){
        try{
            this.tasks.add(ts);
            return 1;
        }catch(Exception e){
            return 0;
        }
    }
    @Override
    public String toString() {
    	return "Monitoring Workflow #"+this.ID;
    }
	@Override
	public String toXmlString() {
		try {
			JAXBContext context= JAXBContext.newInstance(this.getClass());
			Marshaller marshaller=context.createMarshaller();
			marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
			marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true);
			StringWriter sw=new StringWriter();			
			marshaller.marshal(this, sw);
			return sw.toString();
		} catch (JAXBException jaxbe) {
			jaxbe.printStackTrace();
			return "";
		}		
	}
}